package com.sun.dailyprj.usb;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.databinding.DataBindingUtil;

import com.sun.dailyprj.MainActivity;
import com.sun.dailyprj.R;
import com.sun.dailyprj.databinding.ActivityUsbBinding;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Logger;

/*
 * =====================================================================================
 * Summary:
 *
 * File: USBActivity.java
 * Author: Yanpeng.Sun
 * Create: 2019/9/5 11:42
 * =====================================================================================
 */
public class USBActivity extends Activity implements UsbController {
    ActivityUsbBinding mBinding;
    private UsbManager mUsbManager;
    UsbDevice device;
    private PendingIntent mPermissionIntent;

    private UsbCDC usbCDC; //当前连接的USB设备对象
    private MyHandler myHandler; //消息处理中心对象
    private UsbMonitor usbMonitor; //USB监听广播对象
    private Timer timer;
    private TimerTask timerTask;

    public static final String ACTION_DEVICE_PERMISSION = "com.linc.USB_PERMISSION";

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_usb);
        mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);

        test();
        initData();
        setPorter();

    }

    @Override
    protected void onResume() {
        super.onResume();
        mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_DEVICE_PERMISSION), 0);
        IntentFilter permissionFilter = new IntentFilter(ACTION_DEVICE_PERMISSION);
        registerReceiver(mUsbReceiver, permissionFilter);

    }

    //加载数据
    private void initData() {
        myHandler = new MyHandler(mBinding.mTvSendMessageShow, mBinding.mTvReceiveMessageShow, mBinding.mTvUsbDataShow, mBinding.mBtSend, mBinding.mBtSendTiming, this, this); //实例化消息处理中心
        usbMonitor = new UsbMonitor(this, this, mBinding.mTvUsbDataShow); //实例化USB广播监听
        usbMonitor.register(); //注册USB广播监听，注册之后，才可以正常监听USB设备
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void test() {
        HashMap<String, UsbDevice> deviceHashMap = mUsbManager.getDeviceList();
        Iterator<UsbDevice> iterator = deviceHashMap.values().iterator();
        while (iterator.hasNext()) {

            UsbDevice device1 = iterator.next();

            mBinding.tv.append("\ndevice name: " + device1.getDeviceName() +
                    "\ndevice product name:" + device1.getProductName() +
                    "\ndevice product id: " + device1.getProductId() +
                    "\nvendor id:" + device1.getVendorId() +
                    "\ndevice serial: " + device1.getSerialNumber());
            device = device1;
        }
    }

    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            mBinding.tv.append("BroadcastReceiver in\n");
            if (ACTION_DEVICE_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if (device != null) {
                            mBinding.tv.append("usb EXTRA_PERMISSION_GRANTED");
                        }
                    } else {
                        mBinding.tv.append("usb EXTRA_PERMISSION_GRANTED null!!!");
                    }
                }
            }
        }
    };

    public void onSendClick(View view) {
        //开启新线程进行数据发送
        new Thread(new Runnable() {
            @Override
            public void run() {
                usbCDC.send("UDisk test message"); //向当前连接的USB设备发送消息
            }
        }).start();
    }

    public void onSendTimingClick(View view) {
        //判断计时器是否为空，不为就代表正在执行计时任务，就停止当前任务
        if (timer != null) {
            timer.cancel(); //停止计时器
            timer = null; //计时器设为空
            mBinding.mBtSendTiming.setTextColor(Color.BLACK); //改变定时发送控件的颜色
            mBinding.mBtSendTiming.setText("定时发送"); //控件 恢复为“定时发送”
        } else {
            //如果为空，就开始定时发送任务
            timer = new Timer(); //创建定时器
            timerTask = new TimerTask() //创建定时任务
            {
                @Override
                public void run() {
                    //定时任务要执行的内容
                    usbCDC.send("timer message");
                }
            };
            new Thread(new Runnable() //开启新线程执行 开启计时器
            {
                @Override
                public void run() {
                    //开启计时器
                    timer.schedule(timerTask, 0, 20);
                }
            }).start();
            mBinding.mBtSendTiming.setTextColor(Color.RED);
            mBinding.mBtSendTiming.setText("停止"); //计时器开始后“定时发送”控件就改变颜色和字体

        }

    }

    public void onClearClick(View view) {
        mBinding.mTvSendMessageShow.setText("");
        mBinding.mTvReceiveMessageShow.setText("");
        mBinding.mTvSendMessageShow.scrollBy(0, 0);
        mBinding.mTvReceiveMessageShow.scrollBy(0, 0);
    }


    @Override
    public void onDeviceInsert(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice) {
        System.out.println("onDeviceInsert() usbDevice:");
        usbMonitor.requestOpenDevice(usbDevice); //请求USB连接权限
    }

    @Override
    public void onDevicePullOut(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice) {
        closeAll(); //执行关闭所有连接的方法
        myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED); //向消息中心发送 断开连接 信息
    }

    @Override
    public void onDeviceOpen(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice) {
        usbCDC = new UsbCDC(myHandler); //创建USB连接的对象
        UsbDeviceConnection connection = usbManager.openDevice(usbDevice); //获取此USB链路
        usbCDC.openCDC(usbDevice, connection); //连接USB设备（打开USB设备）
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        closeAll();//执行关闭所有连接的方法
        myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);//向消息中心发送 断开连接 信息
    }

    //关闭所有连接
    public void closeAll() {
        if (usbCDC != null) {
            usbCDC.close();
            usbCDC = null;
        }
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    //展示设置波特率dialog的对象，用一个AlertDialog让用户进行选择比特率
    private void setPorter() {
        final String[] items = {"2400", "4800", "9600", "19200", "38400", "57600", "115200", "230400", "460800", "1700000", "2300000", "3400000"};
        AlertDialog.Builder listDialog = new AlertDialog.Builder(this);
        listDialog.setTitle("设置波特率");
        listDialog.setItems(items, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                //判断当前USB设备是否连接，连接之后才可以设置波特率
                if (usbCDC != null) {
                    boolean porter = usbCDC.configUsb(Integer.parseInt(items[which])); //执行设置波特率的对象，返回true代表设置成功
                    mBinding.tv.setText(porter ? "波特率：" + items[which] : "波特率：9600"); //设置波特率对象返回true才改变控件字体，否则设置失败，不改变控件字体
                } else {
                    //判断当前USB设备是否连接，未连接则提示 设备未连接
                    Toast.makeText(USBActivity.this, "设备未连接", Toast.LENGTH_LONG).show();
                }
            }
        });
        listDialog.show(); //展示dialog
    }

}
